function chunk(ary,num){
  var res=[]
  res.push(ary.slice(0,num))//截取
  ary.splice(0,num)//从第几项开始删除几个
  res.push(ary)
  return res
}


function compact(ary){
  var res=[]
  ary.forEach(it=>{
    if(it){
      res.push(it)
    }
  })
  return res
}


function concat(ary,...args){
  var res=[...ary]
  res=res.concat(...args)
  return res
}


function difference(ary,diffary){
  return	ary.reduce((res,it)=>{
    if	(!diffary.includes(it)){
        res.push(it)
      }
      return res
    },[])
  }


function differenceBy(ary,vary,fgen){//迭代器
   var nums=difference(ary,vary)
   var gen=fgen()
   var res=[]
   for (let value of gen){
      if(gen.next().done){
        res.push(value)
      }
   }
    return  difference(nums,res)
}

function drop(ary,n=1){
  ary.splice(0,n)
  return ary
}

function dropRight(ary,n=1){
  ary.reverse()
  ary.splice(0,n)
  ary.reverse()
  return ary
}

function dropRightWhile(ary,f){
  var res=[]
  ary.forEach(it=>{
    if(f(it)){
      res.push(it)
    }
  })
  return res
}

function fill(ary,...args){
    if(args.length===1){
      var n= args[0]
      ary.forEach((it,index)=>{
        ary[index]=n
      })
      return ary
    }
    var n=args[0]
    var start=args[1]
    var end=args[2]
    for(let i = start ; i<end;i++){
      ary[i]=n
    }
    return ary
  }


  function findIndex(ary,f){
    function objlength(obj1,obj2){
      var l1=Object.keys(obj1).length
      var l2=Object.keys(obj2).length
      var flag=0
      if(l1===l2){
        for (let key in obj1){
          if(obj1[key]===obj2[key]){
            flag++
          }
        }
      }
      return l1==flag
    }
  
    var nums=-1
    var flagfun=({}).toString.call(f)==="[object Function]"
    var flagObj=({}).toString.call(f)==="[object Object]"
    var flagkey=({}).toString.call(f)==="[object String]"
    ary.forEach((it,index)=>{
      if(flagfun){
        if(f(it)){
          nums=index
        }
      }
    if(flagObj && objlength(it,f)){
      nums=index
      }
    if(flagkey && it[f]){
      nums=index
    }
    })
    return nums
}


function findLastIndex(ary,f){
  function objlength(obj1,obj2){
    var l1=Object.keys(obj1).length
    var l2=Object.keys(obj2).length
    var flag=0
    if(l1===l2){
      for (let key in obj1){
        if(obj1[key]===obj2[key]){
          flag++
        }
      }
    }
    return l1==flag
  }

  var nums=-1
  var flagfun=({}).toString.call(f)==="[object Function]"
  var flagObj=({}).toString.call(f)==="[object Object]"
  var flagkey=({}).toString.call(f)==="[object String]"
  for(var i=ary.length-1;i>=0;i--){
    var it=ary[i]
    if(flagfun){
      if(f(it)){
        nums=i
      }
    }
    if(flagObj && objlength(it,f)){
      nums=i
      }
    if(flagkey && it[f]){
      nums=i
   }
 }
    return nums
}

function flatten(args){
  return [].concat(...args)
}


function flattenDeep(ary,res=[]){
  ary.forEach(it=>{
    if(({}).toString.call(it)==='[object Array]'){
      flattenDeep(it,res)
    }else{
      res.push(it)
    }
  })
  return res
}




function flattenDepth(ary,path){
  for(let i= 0 ; i<=path;i++){
    ary=[].concat(...ary)
  }
  return ary
}

function fromPairs(ary){
  var map={}
  ary.forEach((it,index)=>{
    map[it[0]]=it[1]
  })
  return map
}

function head(ary){
  return ary[0]
}

function indexOf(ary,value,index=0){
  if(index<0){
    for(    let i = ary.length-(index*-1);i>=0;i--){
      if(ary[i]===value){
        return i
      }
    }
  }
  for(let i = index;i<ary.length;i++){
    if(ary[i]===value){
      return i
    }
  }
  return -1
}

function initial(ary){
  ary.pop()
  return ary
}

function intersection(...args){//多个数组求交际  还是有问题
  var flaglength=args.length
  var isAryflag=true
  var res=[]
  for(let i = 0 ; i <flaglength;i++){//判断输入参数是否正确
    if(!Array.isArray(args[i])){
      isAryflag=false
      break
    }
  }
  if(!isAryflag){
    return '请输入正确的参数'
  }else{
    for(let i = 0;i <flaglength;i++){//遍历得到每个数组
      let it= args[i]
      for(let iti =0 ; iti<it.length;iti++){
        let value=it[iti]
        if(i===flaglength-1){//因为最后一个数组（i+1）已经和前一个(i) 进行了交际
          break
        }
        if(i===0){
          if(args[i+1].includes(value)){//先取第一个和第二个数组的交际
            res.push(value)
          }
          if(iti===it.length-1 && res.length===0){
            return '无交集'  
          }
        }
        if(i>0){
          var flagreslength=res.length //得到
          if(res.includes(value)){
            res.push(value)
            }
          if(iti===it.length-1 && res.length===flagreslength){
              return '无交集'  
          }
        }
      }
    }
  }
  return res
}


function  join(ary,separator=','){
  var str=''
  for(let i = 0 ; i <ary.length;i++){
    if(i===ary.length-1){
      str=srt+ary[i]
      break
    }
    str=str+ary[i]+separator
  }
  return str
}

function last(ary){
  return ary[ary.length-1]
}

function lastIndexOf(ary,value,index=ary.length-1){
  for(let i = index;i>=0;i--){
    var val=ary[i]
    if(val===value){
      return i
    }
  }
  return -1
}

function nth(ary,index=0){
  if(index>=0){
    return ary[index]
  }else{
    return ary[ary.length+index]
  }
}

function isEqual(obj1,obj2){
  function keyAry(obj){ //遍历对象属性，es6新方法，避免for in 遍历原型属性
    return Object.keys(obj)
  } 
  function objLength(obj){//返回对象属性个数
    return keyAry(obj).length
  }
  function isTypeAry(v){//判断array类型
    var typeArray="[object Array]"
    return Object.prototype.toString.call(v)===typeArray
  }//把Object的toString方法call一个新this,比原生typeof更能判断出原生对象类型和宿主对象类型以及各种新类型
  function isTypeObj(v){//判断array类型
    var typeObject="[object Object]"
    return Object.prototype.toString.call(v)===typeObject
  }
  function isNAN(v){//判断NaN类型
    if(v.toString()==='NaN' && v!=v){//NaN=NaN
      return true
    }
    return false
  }
  function isSame(v1,v2){//判断两个数值是否相等
    var flag=false//flag 阀门 防止意外情况
    if(isNAN(v1) && isNAN(v2)){flag=true}//is nan?
    if(isTypeObj(v1) && isTypeObj(v2)){//is obj?
      if(!isEqual(v1,v2)){//不相等则return false
        return false
      }
      flag=true//相等为true
    }
    if(isTypeAry(v1) && isTypeAry(v2)){//同obj
      if(!isSameary(v1,v2)){
        return false
      }
      flag=true 
    }
    if(!flag){//阀门不同
      return false//返回false
    }else{
      return true
    }    
  }
  function isSameary(ary1,ary2){//判断两个数组是否相等
      for(let i=0 ; i<ary1.length;i++ ){
          var aryV1=ary1[i]
          var aryV2=ary2[i]
          if(aryV1!=aryV2){//思路与obj的相似
           if(!isSame(aryV1,aryV2)){//比较两个值，取反
             return false
           }
        }
      }
        return true
      }
  var l1=objLength(obj1)//obj1属性个数
  var l2=objLength(obj2)//obj2属性个数
  if(l1!=l2){//属性个数不同 
    return false
   }else{
    for(let key of keyAry(obj1)){//用这种方法遍历可以用for of 哈哈哈哈
      var value1 = obj1[key]
      var value2 = obj2[key]
      if(value1 != value2){
        if(!isSame(value1,value2)){
          return false
        }
      }
    }
    return true //没有false return true
}
}

var  a ={
  a:[NaN],
  b:{
    b:{
      n:NaN,
      c:[NaN,{
        f:'fuck',
        g:[1,2,3,{
          x:NaN
        }]
      }]
    }
  }
}



function pull(array,...args){
  for(let i = array.length-1 ; i>=0;i--){
    var value = array[i]
    if(args.includes(value)){
      array.splice(i,1)
    }
  }
   return array
}


function pullAll(array,args){
  for(let i = array.length-1 ; i>=0;i--){
    var value = array[i]
    if(args.includes(value)){
      array.splice(i,1)
    }
  }
   return array
}

function pullAllBy(ary1,ary2,key){
  for(let val of ary2){
    for(let i = ary1.length-1; i>=0;i--){
      var value=ary1[i]
      if(val[key]===value[key]){
        ary1.splice(i,1)
      }
    }
  }
  return ary1
}

function pullAt(array, ...indexs){
  var res =[]
  for (let i=array.length-1;i>=0;i--){
    if(indexs.includes(i)){
      res.push(array[i])
      array.splice(i,1)
    }
  }
  return res.reverse()
}

function pullAllWith(ary,args,f){
  for(let othvalue of args){
    for(let i = ary.length-1;i>=0;i--){
      var aryval = ary[i]
      if(f(othvalue,aryval)){
        ary.splice(i,1)
      }
    }
  }
 return ary
}

function remove(ary,f){
  var res=[]
  var nums=ary
  for(let i=0;i<ary.length;i++){
    var value =ary[i]
    if(f(value,i,nums)){
      res.push(value)
      ary.splice(i,1)
    }
  }
  return res
}

function reverse(array){
  var j=0
  var valueZ=array[0]
  for(let i=array.length-1;i>=0;i--){
    if(i!=0){
      array[j++]=array[i]
    }else{
      array[j++]=valueZ
    }
  }
  return array
}

function slice(ary,start=0,end=ary.length){
  var res=[]
  for(let i = start;i<end;i++){
    res.push(ary[i])
  }
  return res
}

function sortedIndex(array, value){
  array.sort((a,b)=>a-b)
  for (let i = 0;i<array.length;i++){
    var val1=array[i]
    var val2=array[i+1]
    if(value<=val1 && i===0){
      return i
    }
    if(value > val1 && value<=val2){
      return ++i
    }
    if(value > val1 && i ===array.length-1 ){
      return ++i
    }
  }
}

function sortedIndex(ary,value){
  ary.push(value)
  ary.sort((a,b)=>a-b)
  for(let i =0;i<ary.length;i++){
    var val=ary[i]
    if(value===val){
      return i
    }
  }
  return -1
 }

function sortedIndexBy(array, value,f){
  var value=f(value)
  for (let i = 0;i<array.length;i++){
    var val1=f(array[i])
    if(value<=val1 && i===0){
      return i
    }
    if(value > val1){
      if(i!=array.length-1){
        if( value<=f(array[i+1])){
          return ++i
        }
      }
    }
    if(i ===array.length-1){
      return ++i
    }
  }
}

function sortedIndexOf(array, value){
  var value = value.toString(2)
  for(let i =0;i<array.length;i++){
    var val=array[i].toString(2)
    if(value===val){
      return i
    }
  }
  return -1
}
function sortedLastIndex(ary,value){
 ary.push(value)
 ary.sort((a,b)=>a-b)
 for(let i =ary.length-1;i>=0;i--){
   var val=ary[i]
   if(value===val){
     return i
   }
 }
 return -1
}


function sortedUniq(ary){
  return Array.from(new Set(ary))
}

function sortedUniq(ary){
  return ary.reduce((res,it)=>{
    if(!res.includes(it)){
      res.push(it)
    }
    return res
  },[])
}


function sortedUniqBy(ary,f){
  var res=[]
  var nums=[]
  var last=0
  ary.forEach((it,index)=>{
    res.push(f(it))
  })
 for(let i = 0 ; i<ary.length;i++){
   var value=f(ary[i])
   if(i===0){
     nums.push(ary[i])
     last=value
   }else{
     if(res.includes(value) && value!=last){
      nums.push(ary[i])
      last=value
     }
   }
 }
 return nums
}

function tail(ary){
  ary.shift(ary[0])
  return ary
}

function take(ary, n=1){
  var res=[]
  if(n>ary.length){
    return ary
  }
  for(let i = 0 ; i<n;i++){
    res.push(ary[i])
  }
  return res
}

function takeRight(ary, n=1){
  var res=[]
  if(n>ary.length){
    return ary
  }
  var j= ary.length-1
  for(let i = 0 ; i<n;i++){
    res.push(ary[j--])
  }
  return res.reverse()
}

function takeRightWhile(array, f){
  var res=[]
  for(let i = array.length-1;i>=0;i--){
    var value=array[i]
    if(f(value,i,array)){
      res.push(value)
    }
  }
  return res.reverse()
}

function takeWhile(ary,f){
  var res=[]
  for(let i = 0;i<ary.length;i++){
    var value=ary[i]
    if(f(value,i,ary)){
      res.push(value)
    }
  }
  return res
}

function union(...args){
  var res=[]
  for(let v of args){
    res=res.concat(v)
  }
 return Array.from(new Set(res))
}

function unionBy(...args){
  var f= args[args.length-1]
  args.pop()
  var res=[]//展开全部数组
  var nums=[]//经过函数改变的数组
  var ary=[]//要返回的数组
  var othary=[]
  var flag=true
  for(let v of args){
    res=res.concat(v)
  }
  if(isFun(f)){
    res.forEach(it=>{
      nums.push(f(it))
      flag=false
    })
  }else{
    res.forEach(it=>{
      nums.push(it[f])
    })
  }
  for(let i = 0 ; i <res.length;i++){
    var value=flag?res[i][f]:f(res[i])
    if(i===0){//第一个数要放进去
      ary.push(res[i])
      othary.push(value)
    }else{
      if(nums.includes(value) && !othary.includes(value)){
        ary.push(res[i])
        othary.push(value)
      }
    }
  }
  return ary
}

function unionWith(...args){//不明白什么意思
  var f=args[args.length-1]
  var ary=args[0]
  var res=[].concat(ary)
  var othary=args[1].reverse()
  var nums=[]
  ary.forEach((obj)=>{
    for(let i = othary.length-1;i>=0;i--){
       var othobj=othary[i]
       if(othary.length!=0){
        if(!f(obj,othobj) && !nums.includes(othobj)){
          res.push(othobj)
          othary.splice(i,1)
        }else{
          nums.push(othobj)
        }
       }
    }
  })
 return res
}


function uniq(ary){
  return ary.reduce((res,it)=>{
    if(!res.includes(it)){
      res.push(it)
    }
    return res
  },[])
}

function uniqBy(ary,f){
  var res=[]
  var nums=[]
  var othary=[]
  ary.forEach(it=>{
    res.push(f(it))
  })
  ary.forEach((it,i)=>{
    var value=f(it)
    if(i===0){
      nums.push(it)
      othary.push(value)
    }else{
      if(res.includes(value) && !othary.includes(value)){
        nums.push(it)
        othary.push(value)
      }
    }
  })
  return nums
}

function uniqWith(ary,f){
  var res=[]
  for(let i = 0 ; i <ary.length;i++){
    var val1=ary[i]
    for(let j=0;j<ary.lengtj;j++){
      var val2=ary[2]
      if(i!=j){
        if(f(val1,val2)){
          res.push(val1)
        }
      }
    }
  }
}


function zip(...args){
  var res=[]
  var j = 0
  var resl = args[1].length
  for(let i=0 ; i <resl ;i++){
     var nums=[]
    args.forEach((it,index)=>{
      nums.push(it[j])
    })
    ++j
    res.push(nums)
  }
  return res
}

function unzip(ary){
  var res=[]
  var resl = ary[0].length
  var j = 0
  for(let i = 0 ; i <resl;i++){
    var nums=[]
    ary.forEach(it=>{
      nums.push(it[j])
    })
   res.push(nums)
   ++j
  }
}

function unzipWith(ary,f){
  var res=unzip(ary)
  var ary=[]
  res.forEach(it=>{
    ary.push(f(...it))
  })
  return ary
}


function without(array, ...values){
  return array.reduce((res,v)=>{
    if(!values.includes(v)){
      res.push(v)
    }
    return res
  },[])
}


function xor(ary1,ary2){
  var res1=[]
  var res2=[]
  ary1.forEach(it=>{
    if(!ary2.includes(it)){
      res1.push(it)
    }
  })
  ary2.forEach(it=>{
    if(!ary1.includes(it)){
      res2.push(it)
    }
  })
  return [].concat(...res1,...res2)
}

function xorBy(...args){
  var res=[]
  var f= args[args.length-1]
  var ary1=args[0]
  var ary2=args[1]
  var nums1=ary1.map(it=>{return f(it)})
  var nums2=ary2.map(it=>{return f(it)})
  for(let i = 0 ; i <ary1.length;i++){
    var value=f(ary1[i])
    if(!nums2.includes(value)){
      res.push(ary1[i])
    }
  }
  for(let i = 0 ; i <ary2.length;i++){
    var value=f(ary2[i])
    if(!nums1.includes(value)){
      res.push(ary2[i])
    }
  }
  return res
}



function xorWith(...args){
  var f= args[args.length-1]
  var ary1=args[0]
  var ary2=args[1]
  function deep(ary1,ary2,f){
    var res=[]
    ary1.forEach((it)=>{
      var flag=false
      for(let v of ary2){
        if(f(it,v)){
          flag=true
        }
      }
      if(!flag){
        res.push(it)
      }
    })
    return res
  }
  return [].concat(...deep(ary1,ary2,f),...deep(ary2,ary1,f))
}

function zipObject(keyres,valres){
  var map={}
  keyres.forEach((it,i)=>{
    map[it]=valres[i]
  })
  return map
}


function zipWith(...args){
  var f= args[args.length-1]
  args.pop()
  var l = args[0].length
  var res=[]
  var j = 0
  for(let i = 0 ; i <l ;i++){
    var nums=[]
    args.forEach(it=>{
      nums.push(it[j])
    })
    ++j
    res.push(nums)
  }  
  return res.map(it=>{
    return f(...it)
  })
}

function countBy(ary,f){
  var obj={}
  ary.forEach(it=>{
    var key = f(it)
    if(key in obj){
      obj[key]++
    }else{
      obj[key]=1
    }
  })
  return obj
}

function every(ary,f){
  if(({}).toString.call(f)==='[object Function]'){
    for(let v of ary){
      if(!(v)){
        return false
      }
    }
    return true
  }
  if(({}).toString.call(f)==='[object Array]'){
    var key = f[0]
    var val=f[1]
    for(let v of ary){
      if(v[key]!=val){
        return false
      }
    }
    return true
  }
  if(({}).toString.call(f)==='[object Object]'){
    for(let v of ary){
      if(!isEqual(v,f)){
        return false
      }
    }
    return true
  }
  if(({}).toString.call(f)==='[object String]'){
    for(let v of ary){
      if(!v[f]){
        return false
      }  
    }
    return true
  }
}

function forEach(obj,f){
  var keys=Object.keys(obj)
  for(let key of keys){
    f(obj[key],key,obj)
  }
}

function forEachRight(obj,f){
  var keys=Object.keys(obj)
  for(let i = keys.length-1;i>=0;i--){
      f(obj[keys[i]])
  }
}

function isAry(v){
  return Object.prototype.toString.call(v)===`[object Array]`
}
function isObj(v){
  return Object.prototype.toString.call(v)===`[object Object]`
}
function isStr(v){
  return Object.prototype.toString.call(v)===`[object String]`
}
function isFun(v){
  return Object.prototype.toString.call(v)===`[object Function]`
}

function filter(ary,f){
  var res=[]
  for(let i=0;i<ary.length;i++){
    var value = ary[i]
    if(isFun(f)){
      if(f(value)){
        res.push(value)
      }
    }
  }
  return res
}

function find(ary,f){
  for(let i = 0 ; i < ary.length ; i++){
    var value = ary[i]
    if(isFun(f)){
      if(f(value,i,ary)){
        return value
      }
    }
    if(isObj(f)){
      var flag=true
      var keysF=Object.keys(f)
      for(let key of keysF){
        if(f[key]!=value[key]){
          flag=false
          break
        }
      }
      if(flag){
        return value
      }
    }
    if(isStr(f)){
      if(value[f]){
        return value
      }
    }
    if(isAry(f)){
      var key = f[0]
      var val=f[1]
      if(value[key]===val){
        return value
      }
    }
  }
  return undefined
}

function findLast(ary,f){
  var ary=ary.reverse()
  return find(ary,f)
}

function flatMap(ary,f){
  var res =ary.map(it=>{
    return f(it)
  })
  return flattenDeep(res)
}
function flattenDeep(ary,res=[]){
  for(let v of ary ){
    if(Object.prototype.toString.call(v)===`[object Array]`){
      flattenDeep(v,res)
    }else{
      res.push(v)
    }
  }
  return res
}

function flatMapDepth(ary,f,depth=1){
  var res =ary.map(it=>{
    return f(it)
  })
  var nums
  for(let i = 0 ; i<depth;i++){
    nums=[].concat(...res)
  }
  return nums
}

function groupBy(ary,f){
  var map={}
   function beMap(key,v){
     if(map[key]===undefined){
      map[key]=[]
      map[key].push(v)
    }else{
      map[key].push(v)
    }
    return map
   }
  for(let v  of  ary){
    if(isFun(f)){
      var key = f(v)
      beMap(key,v)
    }
    if(isStr(f)){
      var key = v[f]
     beMap(key,v)
    }
  }
  return map
}


function includes(ary,v,depth=0){
  if(isObj(ary)){
    var keys=Object.keys(ary)
      if(depth>=0){
        if(depth>keys.length-1){return false}
        for(let i = depth ; i < keys.length ; i++){
          var val=ary[keys[i]]
          if(val===v){
            return true
          }
        }
      }
      if(depth<0){
        depth=ary.length+depth
        if(depth<0){return false}
        for(let i = depth ; i >=0 ; i--){
          var val=ary[keys[i]]
          if(val===v){
            return true
          }
        }
      }
    }
    if(isAry(ary)){
      if(depth>=0){
        if(depth>ary.length-1){return false}
        for(let i =depth ; i <ary.length;i++){
          var val=ary[i]
          if(val===v){
            return true
          }
        }
      }
      if(depth<0){
        depth=ary.length+depth
        if(depth<0){return false}
        for(let i = depth ; i>=0 ; i --){
          var val=ary[i]
          if(val===v){
            return true
          }
        }
      }
    }
    if(isStr(ary)){
      var ary=ary.split('')
      var v=v.split('')
      var index=0
     for(let i=0; i<v.length ; i++){
       var val = v[i]
       if(ary.includes(val)){
        index=ary.indexOf(val)
         break
       }
     }
     var j = 0
     for(let i =  index ; i <=ary.length ; i++){
       if(j<v.length){
        var val = ary[i]
        if(val!=v[j]){
          return false
        }
       }else{
         return true
       }
       ++j
     }
    }
    return false
  }


function invokeMap(ary,f,...args){
 var res=[]
  if(isStr(f)){
    for(let v of ary){
      v=v[f](...args)
      res.push(v)
    }
  }
  if(isFun(f)){
    for(let v of ary){
      v = f.call(v,...args)
      res.push(v)
    }
  }
  return res
}

function keyBy(set,f){
  var map = {}
  if(isFun(f)){
    for(let v of set){
      var key=f(v)
      map[key]=v
    }
  }
  if(isStr(f)){
    for(let v of set){
      var key = v[f]
      map[key]=v
    }
  }
  return map
}

function map(set,f){
  var res=[]
  if(isAry(set)){
    for(let v of set){
      if(isFun(f)){res.push(f(v))}
      if(isStr(f)){res.push(v[f])}
    }
  }
  if(isObj(set)){
    var keys = Object.keys(set)
    for(let key of  keys){
      res.push(f(set[key]))
    }
  }
  return res
}

function partition(set,f){
  var res=[]
  var falsRes=[]
  var truRes=[]
  for(let v of set){
    if(isFun(f)){
      if(f(v)){
        truRes.push(v)
      }else{
        falsRes.push(v)
      }
    }else if(isStr(f)){
      if(v[f]){
        truRes.push(v)
      }else{
        falsRes.push(v)
      }
    }else if(isObj(f)){
      var flag=true
      var keys  = Object.keys(f)
      for(let key of keys){
        if(v[key]!=f[key]){
          falsRes.push(v)
          flag=false
          break
        }
      }
      if(flag){truRes.push(v)}
    }else if(isAry(f)){
      var key=f[0]
      var value=f[1]
      if(v[key]===value){
        truRes.push(v)
      }else{
        falsRes.push(v)
      }
    }
  }
  res.push(truRes)
  res.push(falsRes)
  return res
}



function reduce(set,f,firstV){
  if(isAry(set)){
     var flag=true
     if(!firstV && firstV!=0){
       firstV=set[0]
       flag=false
       }
     for(let i = flag?0:1 ; i < set.length ;i++){
      firstV=f(firstV,set[i],i,set)
     }
    }else if(isObj(set)){
      var keys =Object.keys(set)
      if(!firstV){
        firstV=set[keys[0]]
      }
      for(let i = firstV?0:1 ; i <keys.length;i++){
        var key = keys[i]
        firstV=f(firstV,set[i],key,set)
   }
  }
  return firstV
}

function reduceRight(set,f,firstV){
  if(isAry(set)){
    set.reverse()
    return reduce(set,f,firstV)
  }else if(isObj(set)){
    var map = {}
    var keys=Object.keys(set)
    for(let i = keys.length-1; i >=0 ; i--){
      map[keys[i]]=set[keys[i]]
    }
    return reduce(set,f,firstV)
  }
}


function reject(set,f){
  var res=[]
  set.forEach((v,i, set)=>{
      if(isFun(f)){
        if(!f(v,i,set)){
          res.push(v)
        }
      }else if(isStr(f)){
        if(!v[f]){
          res.push(v)
        }
      }else if(isObj(f)){
        var keys=Object.keys(f)
        for(let key of keys){
          if(f[key]!=v[key]){
            res.push(v)
            break
          }
        }
      }else if(isAry(f)){
        var key = f[0]
        var value = f[1]
        if(v[key]!=value){
          res.push(v)
        }
      }
    })
  return res
}

function sample(ary){
  var index = Math.random()*10|0
 if(index<=ary.length-1){
   return ary[index]
 }else{
  return sample(ary)
 }
}

function size(set){
  if(isAry(set) || isStr(set)){
    return set.length
  }else if(isObj(set)){
    return Object.keys(set).length
  }
}

function some(set,f){
  var keys = Object.keys(set)
  for(let i=0;i<keys.length;i++){
    var value=set[keys[i]]
    if(isFun(f)){
      if(f(value)){
        return true
      }
    }else if(isObj(f)){
      var flag=0
      var fKeys=Object.keys(f)
      for(let i = 0 ; i<fKeys.length;i++){
        if(value[fKeys[i]]===f[keys[i]]){
          flag++
        }
      }
       if(flag===fKeys.length){
         return true
       }
    }else if(isStr(f)){
      if(value[f]){
        return true
      }
    }else if(isAry(f)){
      var key=f[0]
      var v = f[1]
      if(value[key]===v){
        return true
      }
    }
  }
  return false
}


function after(n,f){
  var i =0
  return function(...args){
    ++i
    if(i>=n){
    return  f(...args)
    }
  }
}

function ary(func, n=func.length){
  return function(...args){
    return func(...args)
  }
}


function before(n,fun){
  var i = 0
  console.log(this)
  return function(...args){
    ++i
    if(i>=n){
      return fun.call(this,...args)
    }
  }.bind(this)
}

function bind(func, thisArg, ...Vargs){
  return function(...args){
    return func.call(thisArg,...Vargs,...args)
  }
}

function bindKey(object, key, ...Vargs){
  return function(...args){
    return object[key](...Vargs,...args)
  }
}

function curry(f,n=f.length){
  return function(...args){
    if(args.length>=n){
      return f(...args)
    }else{
      return curry(f.bind(null,...args),n=f.length-args.length)
    }
  }
}

function debounce(func,wait=0,options={leading:false,maxWait:null,trailing=true}){
  var id
  return function(...args){
    if(!options.leading && options.leading && wait!=0){
      func(...args)
      return 
    }
    clearTimeout(id)
    if(wait>=options.maxWait && options.maxWait){
      wait=maxWait
    }
    if(options.trailing && options.leading){
      id=setTimeout(()=>{
        func(...args)
      },wait)
    }
  }
}

function defer(func,...args){
  setTimeout(()=>{
    func(...args)
  },0)
}

function delay(func,wait,...args){
  setTimeout(()=>{
    func(...args)
  },wait)
}

function flip(f){
  return function (...args){
    var args=args.reverse()
    return f(...args)
  }
}

function negate(f){
  return function(...args){
     return (!f.call(this,...args))
  }.bind(this)
}

function once(f){
  var i = 0
  var res
  return function(...args){
    ++i
    if(i>1){
      return res
    }else{
      res=f.call(this,...args)
      return res
    }
  }.bind(this)
}


function overArgs(f,args){
   return function (...Args){
     var res=[]
     args.forEach((it,i)=>{
       res.push(it(Args[i]))
     })
    return f(...res)   
  }
}

function partial(f,...Vargs){
  return function(...args){
    return f.call(null,...Vargs,...args)
  }
}

function partialRight(f,...v){
  return function(...args){
    return f(...args,...v)
  }
}

function rearg(f,indexs){
  return function(...args){
    var res=[]
    indexs.forEach(it=>{
      res.push(args[it])
    })
    return f(...res)
  }
}

function rest(func, start=func.length-1){
  return function(...args){
     var res=[]
     for(let i = start ; i < args.length;i++){
       res.push(args[i])
     }
     return func.call(this,res)
  }.bind(this)
}

function spread(f){
  return function(args){
    return f.call(this,...args)
  }
}

function throttle(f,time){
  var lastTime=0
  var lastres
  return function(...args){
    var now =Date.now()
    if(now-lastTime>time){
      lastres=f.call(this,...args)
      lastTime=now
    }
     return lastres
  }
}

function unary(f){
  return function(...args){
    return f(args[0])
  }
}

function wrap(v,f){
  return function(...args){
    return f.call(this,v,...args)
  }
}

function castArray(ary){
  var res=[]
  if(!isAry(ary)){
    if(isStr(ary)){
      ary = ary.split()
    }else if(isObj(ary)){
       res.push(ary)
       return res
      }else{
        if(arguments.length==0){
          return res
        }
        res.push(ary)
        return res
      }
    }
    return ary
  }

  function clone(obj){
    var keys=Object.keys(obj)
    var map={}
    for(let key of keys){
      var val=obj[key]
      map[key]=val
    }
    return map
  }

 function cloneDeep(value){
  function isAry(v){
    return Object.prototype.toString.call(v)===`[object Array]`
  }
  function isObj(v){
    return Object.prototype.toString.call(v)===`[object Object]`
  }
   var map={}
   var res=[]
   var keys=Object.keys(value)
   for(let key of keys){
     var val = value[key]
     if(isObj(value)){
       map[key]=val
     }else{
       res.push(val)
     }
   }
 return isObj(value)?map:res
}

function conformsTo(object, source){
  var keys = Object.keys(object)
  for(let key of keys){
    if(key in source){
      var val=object[key]
      if(source[key](val)){
        return true
      }else{
        return false
      }
    }
  }
}

function isArguments(value){
  return Object.prototype.toString.call(value)===`[object Arguments]`
}

function isEmpty(v){
  if(!v){
    return true
  }
  return Object.keys(v).length>0?false:true
}

function isEqualWith(value,othvalue,f){
  function keyAry(obj){ 
    return Object.keys(obj)
  } 
  var valuekeys=keyAry(value)
  var othvaluekeys=keyAry(othvalue)
  var l1=valuekeys.length
  var l2=othvaluekeys.length
    if(l1=l2){
       for(let key of valuekeys){
         var v1=value[key]
         var v2=othvalue[key]
         if(!f(v1,v2) && !isEqual(v1,v2)){
           return false
         }
        }
    }else{
      return false
    }
    return true
}

function isInteger(v){ 
  return  v%1===0&&!isStr(v)?true:false
}


function isLength(v){
  if(isStr(v)){return false}
  return  v%1===0&&v>=0&&!isStr(v)?true:false
}

function isMatch(object, source){
  var objKeys=Object.keys(object)
  var souKeys=Object.keys(source)
  for(let key of souKeys){
    var objindex =objKeys.indexOf(key)
    if(objindex>-1){
      var objV=object[key]
      var souV=source[key]
      if(objV!=souV){
        return false
      }else{
        return false
      }
    }
  }
   return true
}

function isMatchWith(obj,othobj,f){
  var objKeys=Object.keys(object)
  var souKeys=Object.keys(source)
  for(let key of souKeys){
    var objindex =objKeys.indexOf(key)
    if(objindex>-1){
      var objV=object[key]
      var souV=source[key]
      if(objV!=souV && !f(objV,souV)){
        return false
      }
    }else{
      return false
    }
  }
   return true
}


function isNaN(v){
 if (v.toString()==='NaN'){
   if(v!=v){
     return true
   }else{
     return false
   }
 }
}

function isNil(v){
 return Object.prototype.toString.call(v)==="[object Null]"|| Object.prototype.toString.call(v)==="[object Undefined]" ? true :false
}

function isNull(v){
  return Object.prototype.toString.call(v)==='[object Null]'?true:false
}

function toArray(v){
  var res=[]
  if(!v ||  typeof v === 'number'){
    return res
  }else{
     var keys=Object.keys(v)
     keys.forEach(key=>{
       res.push(v[key])
     })
     return res
    }
}

function toInteger(n){
  return Math.floor(n*1)|0
}

function toPlainObject(...args){
  var map={}
  args.forEach(obj=>{
     for(let key in obj){
       map[key]=obj[key]
     }
  })
  return map
}

function toString(value){
  if(!value && `${value}`!='-0' && `${value}`!='0'){
    return ''
  }else{
    if(value.toString()===-0){
      return '-0'
    }else if(isAry(value)){
      return value.join(',')
    }else{
      return `${value}`
    }
  }
}

function max(ary){
  if(ary.length===0){return undefined}
  return ary.reduce((max,it)=>{
    if(it>max){
      max=it
    }
    return max
  })
}

function maxBy(array, f){
  var flag=true
  if(array.length===0){return undefined}
  if(isFun(f)){
    var max=f(array[0])
  }else if(isStr(f)){
    var max = array[0][f]
    flag=false
  }
  var maxindex=0
  for(let i = 1 ; i<array.length;i++){
    if(flag){var value = f(array[i])}else{
      var value = array[i][f]
    }
    if(value>max){
      max=value
      maxindex=i
    }
  }
 return array[maxindex]
}

function mean(ary){
  var v=0
  ary.forEach(it=>{
    v=v+it
  })
 return v/ary.length
}

function meanBy(ary,f){
  var v = 0
  var flag=true
  if(isStr(f)){flag=false}
  ary.forEach(it=>{
    if(flag){
      v=v+f(it)
    }else{
      v=v+it[f]
    }
  })
  return v/ary.length
}

function min(ary){
  if(!ary.length){return undefined}
  return ary.reduce((min,it)=>{
     if(it<min){
       min=it
     }
     return min
  })
}

function minBy(ary,f){
  var flag=true
  if(isStr(f)){flag =false}
  var minIndex=0
  var min= flag?f(ary[0]):ary[0][f]
  for(let i = 1 ; i <ary.length ; i++){
    var val = flag?f(ary[i]):ary[i][f]
    if(val<min){
      min=val
      minIndex=i
    }
  }
  return ary[minIndex]
}

function sum(ary){
  return ary.reduce((f,a)=>{
    return f+a
  })
}

function sumBy(ary,f){
  var flag=true
  if(isStr(f)){flag=false}
  var dig= 0
  for(let v of ary){
    if(flag){var val = f(v)}else{
      var val = v[f]
    }
   dig=dig+val
  }
  return dig
}

function clamp(n, l, u){
 if(n>=l && n<u){
   return n
 }else if(n<l){
   return l
 }else{
   return u
 }
}

function inRange(n,s,e){
  if(!e){
    s=0
    if(n>=s){
      return true
    }else{
      return false
    }
  }else{
    if(s>e){
      [s,e]=[e,s]
    }
    if(n>=s && n<e){
      return true
    }else{
      return false
    }
  }
}

function assign(obj,...objes){
 objes.forEach(it=>{
   var keys=Object.keys(it)
   for(let key of keys){
     obj[key]=it[key]
   }
 })
 return obj
}

function assignIn(obj,...objs){
  objs.forEach(it=>{
    for(let key in it){
      obj[key]=it[key]
    }
  })
 return obj
}


function assignInWith(object,...args){
  var f=args[args.length-1]
  args.pop()
  args.forEach(obj=>{
    var keys=Object.keys(obj)
    for(var key of keys){
      var v1=object[key]
      var v2=obj[key]
      var value = f(v1,v2,key,object,args)
      object[key]=value?value:v2
    }
  })
  return object
}

function assignWith(object,...args){
  var f=args[args.length-1]
  args.pop()
  args.forEach(obj=>{
    for(let key in obj){
      var v1=object[key]
      var v2=obj[key]
      var value = f(v1,v2,key,object,args)
      object[key]=value?value:v2
    }
  })
  return object
}


function create(prototype, properties){
 var map ={}
 var keys = Object.keys(properties)
 for(let key of keys){
  prototype[key]=properties[key]
 }
 map.__proto__=prototype
 return map
}

function defaults(object, sources){
 var keys = Object.keys(sources)
 for(let key of keys){
   var v1=object[key]
   var v2=sources[key]
   if(!v1){
    object[key]=v2
   }
 }
 return object
}

function defaultsDeep(obj,othobj){
  var keys = Object.keys(othobj)
  for(let key of keys){
    var v1=object[key]
    var v2=othobj[key]
    object[key]=v2
  }
  return object
}


function findKey(object, f){
  var keys= Object.keys(object)
  for(let key of keys){
    if(isFun(f)){
      if(f(object[key])){
        return key
      }
    }else if(isObj(f)){
      var flag=0
      var val = object[key]
      var fKyes=Object.keys(f)
      for(let fkey of fKyes){
         var v1=val[fkey]
         var v2 = f[fkey]
         if(v1===v2){
           flag++
         }
         if(flag===Object.keys(val).length){
           return key
         }
      }
    }else if(isStr(f)){
      var value=object[key][f]
      if(value){
        return key
      }
    }else if(isAry(f)){
      var Akey=f[0]
      var value=f[1]
      if(object[key][Akey]===value){
        return key
      }
    }
  }
  return undefined
}

function findLastKey(obj,f){
  var map={}
  var keys = Object.keys(obj)
  for(let i = keys.length-1;i>=0;i--){
    var key = keys[i]
    map[key]=obj[key]
  }
  obj=null
  return findKey(map,f)
}

function forIn(obj,f){
  for(let key in obj){
    if(f(obj[key],key,obj)===false){
      return false
    }
  }
}

function forInRight(obj,f){
  var map={}
  var keys=[]
  for(let key in obj){
    keys.push(key)
  }
  for(let i =keys.length-1;i>=0;i--){
    var key=keys[i]
    map[key]=obj[key]
  }
  obj=null
  return forIn(map,f)
}

function forOwn(obj,f){
  var keys= Object.keys(obj)
  for(let key of keys){
    if(f(obj[key],key,obj)===false){
      return false
    }
  }
  return obj
}

function forOwnRight(obj,f){
  var keys= Object.keys(obj).reverse()
  for(let key of keys){
    if(f(obj[key],key,obj)===false){
      return false
    }
  }
  return obj
}

function invert(obj){
  var keys = Object.keys(obj)
  var map = {}
  keys.forEach(key=>{
    var mapkey= obj[key]
    map[mapkey]=key
  })
 return map
}

function invertBy(obj,f){
  var keys = Object.keys(obj)
  var map={}
  keys.forEach(key=>{
    if(isFun(f)){
      var mapkey= f(obj[key])
    }else{
      var mapkey=obj[key]
    }
    var val=key
    if(map[mapkey]){
      map[mapkey].push(val)
      map[mapkey]=map[mapkey]
     }else{
      var res=[]
      res.push(val)
      map[mapkey]=res
    }
  })
  return map
}

function keys(obj){
  var pr=obj.__proto__
  var res=[]
  for(let key in obj){
    if(!(key in pr)){
      res.push(key)
    }
  }
 return res
}

function keysIn(obj){
  var res=[]
  for(let key in obj){
    res.push(key)
  }
 return res
}

function mapKeys(object, f){
   var map={}
   var keys=Object.keys(object)
   keys.forEach(objkey=>{
     var mapkey=f(object[objkey],objkey,object)
     map[mapkey]=object[objkey]
   })
   return map
}

function mapValues(obj,f){
  var keys=Object.keys(obj)
  var map={}
  keys.forEach(it=>{
    if(isFun(f)){
      var value = f(obj[it])
    }else if(isStr(f)){
      var value = obj[it][f]
    }
    map[it]=value
  })
 return map
}

function omit(obj,propos){
  var keys=Object.keys(obj)
  var map={}
  keys.forEach(key=>{
    if(!propos.includes(key)){
      map[key]=obj[key]
    }
  })
  return map
}

function omitBy(obj,f){
  var map={}
  for(let key in obj){
    var value=obj[key]
    if(!f(value)){
      map[key]=value
    }
  }
 return map
}

function pick(obj,propos){
  var map={}
  propos.forEach(key=>{
    map[key]=obj[key]
  })
 return map
}

function pickBy(obj,f){
  var map={}
  for(let key in obj){
    var value=obj[key]
    if(f(value)){
      map[key]=value
    }
  }
 return map
}

function toPairs(obj){
  var res=[]
  var keys=Object.keys(obj)
  for(let key of keys){
    var ary=[]
    ary.push(key)
    ary.push(obj[key])
    res.push(ary)
  }
  return res 
}

function transform(object, f, accumulator){
  var flag=true
  if(isObj(object)){flag = false}
  accumulator = accumulator?accumulator:flag?[]:{}
  var keys=Object.keys(object)
  for(let key of keys){
    key=flag?key*1:key
    val=f(accumulator,object[key],key,object)
    if(val===false){
      break
    }
  }
  return accumulator
}

function values(obj){
  var res=[]
  var P=obj.__proto__
  for(let key in obj){
    if(!(key in P)){
      res.push(obj[key])
    }
  }
  return res
}

function attempt(f,...args){
  for(let arg of args){
    var val = f(arg)
    if(val){
      return val
    }else{
      throw Error(val)
    }
  }
}

function bindAll(obj,fs){
   var keys=Object.keys(obj)
   for(let key of keys){
     if(fs.includes(key)){
       var f= obj[key].bind(obj)
       obj[key]=f
     }
   }
}

function cond(pairs){
  return function(...args){
    for(let fs of pairs){
       for(let f of fs){
         if(f()){
           return f.call(this,...args)
         }
       }
    }
  }
}

function conforms(sou){
  var keys = Object.keys(sou)
  var key=keys[0]
  var f = sou[key]
  return function(obj){
    var res=[]
    var objkeys= Object.keys(obj)
    for(let objkey of keys){
      if(objkey===key){
        var value = obj[objkey]
        if(f(value)){
          return obj
        }
      }
    }
  }
}

function constant(value){
  return function(){
    return value
  }
}

function defaultTo(val,deval){
  if(Number.isNaN(val)){
    return deval
  }else if(!val){
    return deval
  }
  return val
}

function flow(fs){
  var value
  return function(...args){
    for(f of fs){
      if(value){
        value=f(value)
      }else{
        value=f(...args)
      }
    }
    return value
  }.bind(this)
}

function flowRight(fs){
 var fs=fs.reverse()
 return flow(fs)
}

function identity(...args){
  return args[0]
}

function iteratee(f){
  var res=[]
  var flag=0
  if(isObj(f)){
    flag=1
  }else if(isStr(f)){
    flag = 2
  }
  return function(value){
    var keyfalag=0
     if(flag===1){
       var keys=Object.keys(f)
       for(let key of keys){
         var v1=value[key]
         var v2=f[key]
         if(v1===v2){
           keyfalag++
         }
         if(keyfalag===keys.length){
           return true
         }
       }
     }else if(flag===2){
       var v1 = value[f]
       var keys  = Object.keys(value)
       for(let key of keys){
        var v2=value[key]
        if(v1===v2){
          return v2   
        }
       }
     }else{
       var fkey = f[0]
       var val = f[1]
       var keys  = Object.keys(value)
       for(let key of keys){
        var v2 = value[key]
        if(v2==val){
          return value
        }
       }
     }
      return false
    }
}

function matches(othobj){
  var flag=0
  return function(obj){
    var keys=Object.keys(othobj)
    for(let key of keys){
      var v1=othobj[key]
      var v2=obj[key]
      if(v1===v2){
        flag++
      }
      if(flag===keys.length){
        return true
      }
    }
    return false
  }
}


function mixin(object, source, options = { chain: true }) {
  if (isObj(object)) {
    var soukeys = Object.keys(source)
    for (let key of soukeys) {
      object[key] = source[key]
    }
  } else if (isFun(object)) {
    Object.prototype.object = object
  }
  if (options.chain) {
    return this
  }
}

function nthArg(n=0){
  return function (...args){
     return n>=0?args[n]:args[args.length+n]
  }
}


function over(fs){
  var res=[]
  return function (...args){
    fs.forEach(f=>{
     res.push(f(...args))
    })
  return res
  }
}

function overEvery(fs){
  return function(...args){
    for(let i = 0 ; i <fs.length;i++){
      var f = fs[i]
      if(!f(...args)){
        return false
      }
    }
  return true
  }
}

function overSome(fs){
  return function(...args){
    for(let i = 0 ; i <fs.length;i++){
      var f = fs[i]
      if(f(...args)){
        return true
      }
    }
  return false
  }
}

function times(n,f){
  var res=[]
  for(let i = 0 ; i < n ;i++){
     res.push(f(i))
  }
  return res
}

function uniqueId(prefix =''){
  var id =setTimeout(()=>{})
   return prefix+id
}